#include "Sock.hpp"

#include <functional>
#include <vector>
#include <unistd.h>
#include <pthread.h>

namespace bobo
{
    using Func = std::function<void(int)>;

    class TcpServer; // 声明
    struct ThreadData
    {
        ThreadData(int sock, TcpServer *tcpServer)
            : _sock(sock), _tcpServer(tcpServer)
        {}

        int _sock;
        TcpServer *_tcpServer;
    };

    class TcpServer
    {
        static void* Routine(void* args)
        {
            pthread_detach(pthread_self()); // ***************

            ThreadData* td = static_cast<ThreadData *>(args);
            td->_tcpServer->Excute(td->_sock);

            close(td->_sock);
            delete td;

            return nullptr;
        }
    public:
        TcpServer(const uint16_t &port, std::string ip = "")
        {
            _listenSock = _sock.Socket();
            _sock.Bind(_listenSock, port, ip);
            _sock.Listen(_listenSock);
        }
        void Start()
        {
            while (true)
            {
                uint16_t clientPort;
                std::string clientIp;
                int serviceSock = _sock.Accept(_listenSock, &clientPort, &clientIp);
                if (serviceSock == -1) continue; // ***************

                ThreadData* td = new ThreadData(serviceSock, this);
                pthread_t tid;
                pthread_create(&tid, nullptr, Routine, td);
            }
        }
        void BindService(Func func)
        {
            _funcs.push_back(func);
        }
        void Excute(int sock)
        {
            for(auto& f : _funcs)
            {
                f(sock);
            }
        }
        ~TcpServer()
        {
            if (_listenSock >= 0)
                close(_listenSock);
        }

    private:
        int _listenSock;
        Sock _sock;
        std::vector<Func> _funcs;
    };
}